Skip to content

Conversation

@rabi-siddique
Copy link
Contributor

@rabi-siddique rabi-siddique commented Jan 7, 2026

closes:

Description

Removes the dependency on AxelarScan for GMP transaction failure status detection. Instead, it now uses Alchemy WebSocket connections to detect failed GMP transactions on EVM. Alchemy WebSockets are used for both failure and success detection.

This functionality is currently implemented in the live mode of the GMP watcher. Support for lookback mode will be added in a subsequent PR, as detecting reverted transactions in historical logs requires a different mechanism.

Testing Considerations

Existing tests have been adapted to the new changes. Mocks were updated as well. And couple of new tests were added for testing revert behavior.

Upgrade Considerations

  • Requires a new planner deployment.
  • Requires updates to the monitoring and alerting infrastructure to correctly filter and interpret GMP transaction logs.

@rabi-siddique rabi-siddique force-pushed the rs-find-reverted-transactions branch 2 times, most recently from f04b63d to 28b2ce9 Compare January 8, 2026 11:35
@rabi-siddique rabi-siddique changed the title chore: find reverted gmp transactions chore: find reverted gmp transactions in live mode Jan 8, 2026
@rabi-siddique
Copy link
Contributor Author

Logs from earlier e2e testing specifically if tx is made by the Wallet Owner:

errrior from call: Error: execution reverted (unknown custom error) (action="call", data="0x97232f6a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000047478353500000000000000000000000000000000000000000000000000000000", reason=null, transaction={ "data": "0x49160658fc151a77dfc86b108ef0922de0a59b7c613e94b8a1a5fcf8277e9c1f35b5db1e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000661676f7269630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002d61676f726963317277776c65793535306b396d6d6b367571366d6d367a3475647267386b7975797666737a6a6b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004747835350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000010000000000000000000000000075faf114eafb1bdbe2f0316df893fd58ce46aa4d00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000bfc91d59fdaa134a4ed45f7b584caf96d7792eff00000000000000000000000000000000000000000000000000000000000927c000000000000000000000000000000000000000000000000000000000000000000000000000000000bfc91d59fdaa134a4ed45f7b584caf96d7792eff00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084617ba03700000000000000000000000075faf114eafb1bdbe2f0316df893fd58ce46aa4d00000000000000000000000000000000000000000000000000000000000927c00000000000000000000000007a4150a9bf3bee704493b7178c35b7c174b4f6ff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "from": "0xD36aac0c9676e984D72823Fb662ce94D3Ab5E551", "to": "0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF" }, invocation=null, revert=null, code=CALL_EXCEPTION, version=6.13.4)
    at makeError (file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/utils/errors.ts:694:21)
    at getBuiltinCallException (file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/abi/abi-coder.ts:118:12)
    at Function.getBuiltinCallException (file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/abi/abi-coder.ts:235:16)
    at WebSocketProvider.getRpcError (file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/providers/provider-jsonrpc.ts:989:32)
    at file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/providers/provider-jsonrpc.ts:563:45 {
  code: 'CALL_EXCEPTION',
  action: 'call',
  data: '0x97232f6a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000047478353500000000000000000000000000000000000000000000000000000000',
  reason: null,
  transaction: {
    to: '0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF',
    data: '0x49160658fc151a77dfc86b108ef0922de0a59b7c613e94b8a1a5fcf8277e9c1f35b5db1e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000661676f7269630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002d61676f726963317277776c65793535306b396d6d6b367571366d6d367a3475647267386b7975797666737a6a6b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004747835350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000010000000000000000000000000075faf114eafb1bdbe2f0316df893fd58ce46aa4d00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000bfc91d59fdaa134a4ed45f7b584caf96d7792eff00000000000000000000000000000000000000000000000000000000000927c000000000000000000000000000000000000000000000000000000000000000000000000000000000bfc91d59fdaa134a4ed45f7b584caf96d7792eff00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084617ba03700000000000000000000000075faf114eafb1bdbe2f0316df893fd58ce46aa4d00000000000000000000000000000000000000000000000000000000000927c00000000000000000000000007a4150a9bf3bee704493b7178c35b7c174b4f6ff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    from: '0xD36aac0c9676e984D72823Fb662ce94D3Ab5E551'
  },
  invocation: null,
  revert: null,
  shortMessage: 'execution reverted (unknown custom error)',
  info: {
    error: {
      code: 3,
      message: 'execution reverted',
      data: '0x97232f6a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000047478353500000000000000000000000000000000000000000000000000000000'
    },
    payload: { method: 'eth_call', params: [Array], id: 6, jsonrpc: '2.0' }
  }
}
revertData: 0x97232f6a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000047478353500000000000000000000000000000000000000000000000000000000
❌ REVERTED: txId=tx55 txHash=0x08cf25716266f35b89b9b64f090b66ac58170414a50dfcea4f5581f15bc14541 block=231640080 (ContractCallFailed)
Watch result: false

Logs when tx is made non-owner of the Wallet:

~/Desktop/Agoric/agoric-notes> yarn watch
Starting to watch on Arbitrum Sepolia testnet...
subscribed: 0xcb6ee235e2a5269530888c4c111e13a1
errrior from call: Error: execution reverted (unknown custom error) (action="call", data="0xde6a3cbf0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d61676f726963316565396872306a7972786879393939793735356d703836326c6a6779636d77797034706c377100000000000000000000000000000000000000", reason=null, transaction={ "data": "0x49160658a79ce2ad28ae604f0f2474e4407079866e7e9fbccb68f4ea9db25188c7467752000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000661676f7269630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002d61676f726963316565396872306a7972786879393939793735356d703836326c6a6779636d77797034706c37710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004747835350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000010000000000000000000000000075faf114eafb1bdbe2f0316df893fd58ce46aa4d00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000bfc91d59fdaa134a4ed45f7b584caf96d7792eff00000000000000000000000000000000000000000000000000000000000927c000000000000000000000000000000000000000000000000000000000000000000000000000000000bfc91d59fdaa134a4ed45f7b584caf96d7792eff00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084617ba03700000000000000000000000075faf114eafb1bdbe2f0316df893fd58ce46aa4d00000000000000000000000000000000000000000000000000000000000927c00000000000000000000000007a4150a9bf3bee704493b7178c35b7c174b4f6ff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "from": "0xD36aac0c9676e984D72823Fb662ce94D3Ab5E551", "to": "0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF" }, invocation=null, revert=null, code=CALL_EXCEPTION, version=6.13.4)
    at makeError (file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/utils/errors.ts:694:21)
    at getBuiltinCallException (file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/abi/abi-coder.ts:118:12)
    at Function.getBuiltinCallException (file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/abi/abi-coder.ts:235:16)
    at WebSocketProvider.getRpcError (file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/providers/provider-jsonrpc.ts:989:32)
    at file:///home/rabi/Desktop/Agoric/agoric-notes/node_modules/ethers/src.ts/providers/provider-jsonrpc.ts:563:45 {
  code: 'CALL_EXCEPTION',
  action: 'call',
  data: '0xde6a3cbf0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d61676f726963316565396872306a7972786879393939793735356d703836326c6a6779636d77797034706c377100000000000000000000000000000000000000',
  reason: null,
  transaction: {
    to: '0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF',
    data: '0x49160658a79ce2ad28ae604f0f2474e4407079866e7e9fbccb68f4ea9db25188c7467752000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000661676f7269630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002d61676f726963316565396872306a7972786879393939793735356d703836326c6a6779636d77797034706c37710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004747835350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000010000000000000000000000000075faf114eafb1bdbe2f0316df893fd58ce46aa4d00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000bfc91d59fdaa134a4ed45f7b584caf96d7792eff00000000000000000000000000000000000000000000000000000000000927c000000000000000000000000000000000000000000000000000000000000000000000000000000000bfc91d59fdaa134a4ed45f7b584caf96d7792eff00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084617ba03700000000000000000000000075faf114eafb1bdbe2f0316df893fd58ce46aa4d00000000000000000000000000000000000000000000000000000000000927c00000000000000000000000007a4150a9bf3bee704493b7178c35b7c174b4f6ff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    from: '0xD36aac0c9676e984D72823Fb662ce94D3Ab5E551'
  },
  invocation: null,
  revert: null,
  shortMessage: 'execution reverted (unknown custom error)',
  info: {
    error: {
      code: 3,
      message: 'execution reverted',
      data: '0xde6a3cbf0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d61676f726963316565396872306a7972786879393939793735356d703836326c6a6779636d77797034706c377100000000000000000000000000000000000000'
    },
    payload: { method: 'eth_call', params: [Array], id: 4, jsonrpc: '2.0' }
  }
}
revertData: 0xde6a3cbf0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d61676f726963316565396872306a7972786879393939793735356d703836326c6a6779636d77797034706c377100000000000000000000000000000000000000
⚠️  IGNORED: txId=tx55 txHash=0xaaa49b1a63ec7d18e10dd2fa0befc682c3c51033962f0b903f73e34d4f8f20e4 block=231637688 (non-owner or other revert: 0xde6a3cbf)

I’ve made many updates since the last round of testing, so I will need to do E2E testing again.

@rabi-siddique rabi-siddique marked this pull request as ready for review January 8, 2026 12:23
@rabi-siddique rabi-siddique force-pushed the rs-find-reverted-transactions branch from 5bfdeab to 51dd6d0 Compare January 12, 2026 10:32
@rabi-siddique rabi-siddique changed the base branch from master to rs-publish-src-addr January 12, 2026 10:34
@rabi-siddique rabi-siddique force-pushed the rs-find-reverted-transactions branch from b9fde86 to b8b1099 Compare January 12, 2026 12:51
@rabi-siddique
Copy link
Contributor Author

rabi-siddique commented Jan 12, 2026

E2E testing results

Success Case

Processing pendingTx event published.vStoragePusher.portfolios.tx6
New pending tx {
  txId: 'tx6',
  destinationAddress: 'eip155:421614:0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF',
  sourceAddress: 'cosmos:agoricdev-25:agoric1rwwley550k9mmk6uq6mm6z4udrg8kyuyvfszjk',
  status: 'pending',
  type: 'GMP'
}
[tx6] handling GMP tx
{
  blockHeight: 5088146n,
  portfolioEvents: [],
  pendingTxEvents: [
    {
      path: 'published.vStoragePusher.portfolios.tx6',
      value: '{"blockHeight":"5088146","values":["{\\"body\\":\\"#{\\\\\\"destinationAddress\\\\\\":\\\\\\"eip155:421614:0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF\\\\\\",\\\\\\"sourceAddress\\\\\\":\\\\\\"cosmos:agoricdev-25:agoric1rwwley550k9mmk6uq6mm6z4udrg8kyuyvfszjk\\\\\\",\\\\\\"status\\\\\\":\\\\\\"pending\\\\\\",\\\\\\"type\\\\\\":\\\\\\"GMP\\\\\\"}\\",\\"slots\\":[]}"]}',
      eventRecord: {
        blockHeight: 5088146n,
        type: 'kvstore',
        event: { type: 'state_change', attributes: [Array] }
      }
    }
  ]
}
[tx6] Watching transaction status for txId: tx6 at contract: 0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF
  • Tx Resolved:
[tx6] ✅ SUCCESS: txId=tx6 txHash=0x71661be709ec9c3cffd010f49602cf6e0acba9d520906ea423fb3ac3cf9ae168 block=232827903
{
  maxRetries: 6,
  retryIntervalMs: 3500,
  message: 'offer-1768223624201'
}

Revert Case(Authorized User)

  • User tries to deploy more funds than they have: AxelarScan Link

  • Resolver Logs:

Processing pendingTx event published.vStoragePusher.portfolios.tx7
New pending tx {
  txId: 'tx7',
  destinationAddress: 'eip155:421614:0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF',
  sourceAddress: 'cosmos:agoricdev-25:agoric1rwwley550k9mmk6uq6mm6z4udrg8kyuyvfszjk',
  status: 'pending',
  type: 'GMP'
}
[tx7] handling GMP tx
{
  blockHeight: 5088193n,
  portfolioEvents: [],
  pendingTxEvents: [
    {
      path: 'published.vStoragePusher.portfolios.tx7',
      value: '{"blockHeight":"5088193","values":["{\\"body\\":\\"#{\\\\\\"destinationAddress\\\\\\":\\\\\\"eip155:421614:0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF\\\\\\",\\\\\\"sourceAddress\\\\\\":\\\\\\"cosmos:agoricdev-25:agoric1rwwley550k9mmk6uq6mm6z4udrg8kyuyvfszjk\\\\\\",\\\\\\"status\\\\\\":\\\\\\"pending\\\\\\",\\\\\\"type\\\\\\":\\\\\\"GMP\\\\\\"}\\",\\"slots\\":[]}"]}',
      eventRecord: {
        blockHeight: 5088193n,
        type: 'kvstore',
        event: { type: 'state_change', attributes: [Array] }
      }
    }
  ]
}
[tx7] Watching transaction status for txId: tx7 at contract: 0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF
  • Revert detected and resolved:
[tx7] ❌ REVERTED: txId=tx7 txHash=0x88433f939abf53d4a546caf9789a6bda21d7d55f105f38b3b5f177940086b7ca block=232829871 - transaction failed
{ blockHeight: 5088281n, portfolioEvents: [], pendingTxEvents: [] }
{
  maxRetries: 6,
  retryIntervalMs: 3500,
  message: 'offer-1768224223328'
}

mergify bot added a commit that referenced this pull request Jan 12, 2026
…12327)

closes:
- https://github.com/Agoric/agoric-private/issues/699

## Description


Publishes the expected `sourceAddress` (LCA) for pending GMP transactions into vstorage and updates snapshots accordingly.

This enables the GMP watcher to reliably classify reverted Wallet executions by comparing the decoded `sourceAddress` from `calldata` against the expected value, avoiding revert simulation and state-drift issues(see #12311).

### Testing Considerations

The vstorage snapshot tests are enough to verify this change.

### Upgrade Considerations

- Will require a `ymax0` and `ymax1` update on mainnet.
Base automatically changed from rs-publish-src-addr to master January 12, 2026 13:31
@github-actions
Copy link

Base branch is changed to master. Please re-run the integration tests by adding 'force:integration' label.

@rabi-siddique
Copy link
Contributor Author

Revert Case(Non-Authorized)

  • Non-Owner makes a GMP call: AxelarScan Link
    Wallet Owner: agoric1rwwley550k9mmk6uq6mm6z4udrg8kyuyvfszjk
    User making the call: agoric1ee9hr0jyrxhy999y755mp862ljgycmwyp4pl7q

  • Resolver logs:

Processing pendingTx event published.vStoragePusher.portfolios.tx8
New pending tx {
  txId: 'tx8',
  destinationAddress: 'eip155:421614:0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF',
  sourceAddress: 'cosmos:agoricdev-25:agoric1rwwley550k9mmk6uq6mm6z4udrg8kyuyvfszjk',
  status: 'pending',
  type: 'GMP'
}
[tx8] handling GMP tx
{
  blockHeight: 5088334n,
  portfolioEvents: [],
  pendingTxEvents: [
    {
      path: 'published.vStoragePusher.portfolios.tx8',
      value: '{"blockHeight":"5088334","values":["{\\"body\\":\\"#{\\\\\\"destinationAddress\\\\\\":\\\\\\"eip155:421614:0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF\\\\\\",\\\\\\"sourceAddress\\\\\\":\\\\\\"cosmos:agoricdev-25:agoric1rwwley550k9mmk6uq6mm6z4udrg8kyuyvfszjk\\\\\\",\\\\\\"status\\\\\\":\\\\\\"pending\\\\\\",\\\\\\"type\\\\\\":\\\\\\"GMP\\\\\\"}\\",\\"slots\\":[]}"]}',
      eventRecord: {
        blockHeight: 5088334n,
        type: 'kvstore',
        event: { type: 'state_change', attributes: [Array] }
      }
    }
  ]
}
[tx8] Watching transaction status for txId: tx8 at contract: 0x7a4150a9BF3bEE704493B7178c35b7C174b4F6fF
  • Tx Ignored and not resolved:
[tx8] ⚠️  IGNORED: txId=tx8 txHash=0xe791575a559163f688012dcc61cb0780e2ce7a3c2ceff3d7f6ceaa551b22960d - sourceAddress mismatch (expected agoric1rwwley550k9mmk6uq6mm6z4udrg8kyuyvfszjk, got agoric1ee9hr0jyrxhy999y755mp862ljgycmwyp4pl7q)
{ blockHeight: 5088440n, portfolioEvents: [], pendingTxEvents: [] }
{ blockHeight: 5088441n, portfolioEvents: [], pendingTxEvents: [] }

[tx8] ✅ SUCCESS: txId=tx8 txHash=0xc2bffa5df7d84798ed0bf0490a73cef0330260c94d28c7f6c68559ffa7c3c476 block=232832927
{
  maxRetries: 6,
  retryIntervalMs: 3500,
  message: 'offer-1768225192767'
}

@rabi-siddique rabi-siddique force-pushed the rs-find-reverted-transactions branch from b8b1099 to 183e078 Compare January 12, 2026 13:41
Comment on lines +269 to +276
if (result.settled) {
const reason = `${logPrefix} Live mode completed`;
log(reason);
abortController.abort(reason);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about handling tx not settled here?

Comment on lines 216 to 231
return { settled: false };
}

deleteTxBlockLowerBound(kvStore, txId);
return { found: true, txHash: matchingEvent.transactionHash };
return { settled: true, txHash: matchingEvent.transactionHash };
} catch (error) {
log(`Error:`, error);
return { found: false };
return { settled: false };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need some extra identifier to differentiate b/w not found and error? Because both says settled: false

`Watching for MulticallStatus and MulticallExecuted events for txId: ${txId} at contract: ${contractAddress}`,
);
// Named so we can remove it
const onAbort = () => finish({ settled: false });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we wanna explicitly log when we aborted signal? Might help in debugging.

Comment on lines 190 to 193
ws.off('message', messageHandler);
ws.off('error', onWsError);
ws.off('close', onWsClose);
signal?.removeEventListener('abort', onAbort);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a log say: "Cleaning up ws and listeners"..?

Comment on lines 334 to 358
if (!done) {
log(
`✗ No MulticallStatus or MulticallExecuted found for txId ${txId} within ${timeoutMs / 60000} minutes`,
);
const { status, errorMessage } = await findTxStatusFromAxelarscan(
txId,
contractAddress,
{
axelarApiUrl,
fetch,
},
`✗ No transaction status found for txId ${txId} within ${
timeoutMs / 60000
} minutes`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we make done = true on failure as well. So done essentially means that tx is processed? Either success/failed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, done means the watcher is finished (stopped watching), regardless of whether the transaction succeeded, failed, or was never observed.

Comment on lines 276 to 319
if (receipt.status === 1 && matchingLog) {
log(
`✅ SUCCESS: txId=${txId} txHash=${txHash} block=${receipt.blockNumber}`,
);
return finish({ settled: true, txHash });
}

if (receipt.status === 0) {
/**
* Transaction reverted - since we've already validated that the sourceAddress
* matches our expected LCA address, this is a legitimate execution attempt
* from our own wallet that failed. We treat this as a transaction failure.
*
* Note: Spurious executions from unauthorized parties are already filtered
* out by the sourceAddress check above, so any revert we see here represents
* a genuine failure of the user's operation.
*/
log(
`❌ REVERTED: txId=${txId} txHash=${txHash} block=${receipt.blockNumber} - transaction failed`,
);
return finish({ settled: true, txHash });
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it troubling that these two cases collapse into indistinguishable output.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for commenting on this. Looks like I messed it up while defining settled field in all watchers.

Comment on lines 309 to 318
subId = await provider.send('eth_subscribe', [
'alchemy_minedTransactions',
{
addresses: [{ to: contractAddress }],
includeRemoved: false,
hashesOnly: false,
},
]);

ws.on('message', messageHandler);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any chance of a race here? Our general pattern is to register listeners before creating circumstances that could cause them to be invoked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed to attach the message handler before subscribing.

For additional context: at the contract level, we also follow this pattern - we publish the pending tx entry to vstorage before making the GMP call (see pos-gmp.flows.ts#L540-L566), which gives the watcher 50s-3min to start up before the transaction could complete. So we have protection at both levels.

Comment on lines 321 to 324
// Attach listeners (all removable)
ws.on('error', onWsError);
ws.on('close', onWsClose);
signal?.addEventListener('abort', onAbort);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, same issue. Fixed to attach the error/close listeners immediately after defining them

@rabi-siddique rabi-siddique force-pushed the rs-find-reverted-transactions branch from 09dd75a to edd72dd Compare January 20, 2026 13:05
@rabi-siddique
Copy link
Contributor Author

rabi-siddique commented Jan 21, 2026

Things are working as expected:

Portfolio64 logs:

{
  blockHeight: 5228729n,
  portfolioEvents: [
    {
      path: 'published.ymax0.portfolios.portfolio64',
      value: '{"blockHeight":"5228729","values":["{\\"body\\":\\"#{\\\\\\"accountIdByChain\\\\\\":{\\\\\\"agoric\\\\\\":\\\\\\"cosmos:agoricdev-25:agoric1htyk2rhf06eeewtr57v48g6ykyqch6tk3nwjlx5xmt2ug79n0ylqtrfwu6\\\\\\",\\\\\\"noble\\\\\\":\\\\\\"cosmos:grand-1:noble19hwcddzyk3r0rr2m7k6rgemzqzeq9kf9unt44vygnydmetzwhtzs6xlt6x\\\\\\"},\\\\\\"accountsPending\\\\\\":[],\\\\\\"depositAddress\\\\\\":\\\\\\"agoric1lj56zcfftr7w8hgdc749ynt8l8nz4guwf548f097ug9vszsvjeyq8u8upq\\\\\\",\\\\\\"flowCount\\\\\\":1,\\\\\\"flowsRunning\\\\\\":{\\\\\\"flow1\\\\\\":{\\\\\\"amount\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+1000000\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"deposit\\\\\\"}},\\\\\\"nobleForwardingAddress\\\\\\":\\\\\\"noble1f8l404vwnh2p99yqar435fjp5yrclnlyzkm6gw\\\\\\",\\\\\\"policyVersion\\\\\\":1,\\\\\\"positionKeys\\\\\\":[],\\\\\\"rebalanceCount\\\\\\":1,\\\\\\"targetAllocation\\\\\\":{\\\\\\"Aave_Avalanche\\\\\\":\\\\\\"+100\\\\\\"}}\\",\\"slots\\":[\\"board006172\\"]}","{\\"body\\":\\"#{\\\\\\"accountIdByChain\\\\\\":{\\\\\\"agoric\\\\\\":\\\\\\"cosmos:agoricdev-25:agoric1htyk2rhf06eeewtr57v48g6ykyqch6tk3nwjlx5xmt2ug79n0ylqtrfwu6\\\\\\",\\\\\\"noble\\\\\\":\\\\\\"cosmos:grand-1:noble19hwcddzyk3r0rr2m7k6rgemzqzeq9kf9unt44vygnydmetzwhtzs6xlt6x\\\\\\"},\\\\\\"accountsPending\\\\\\":[\\\\\\"Avalanche\\\\\\"],\\\\\\"depositAddress\\\\\\":\\\\\\"agoric1lj56zcfftr7w8hgdc749ynt8l8nz4guwf548f097ug9vszsvjeyq8u8upq\\\\\\",\\\\\\"flowCount\\\\\\":1,\\\\\\"flowsRunning\\\\\\":{\\\\\\"flow1\\\\\\":{\\\\\\"amount\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+1000000\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"deposit\\\\\\"}},\\\\\\"nobleForwardingAddress\\\\\\":\\\\\\"noble1f8l404vwnh2p99yqar435fjp5yrclnlyzkm6gw\\\\\\",\\\\\\"policyVersion\\\\\\":1,\\\\\\"positionKeys\\\\\\":[],\\\\\\"rebalanceCount\\\\\\":1,\\\\\\"targetAllocation\\\\\\":{\\\\\\"Aave_Avalanche\\\\\\":\\\\\\"+100\\\\\\"}}\\",\\"slots\\":[\\"board006172\\"]}","{\\"body\\":\\"#{\\\\\\"accountIdByChain\\\\\\":{\\\\\\"Avalanche\\\\\\":\\\\\\"eip155:43113:0xf5f6ab6628c552baf819dd66229c2325cc722c71\\\\\\",\\\\\\"agoric\\\\\\":\\\\\\"cosmos:agoricdev-25:agoric1htyk2rhf06eeewtr57v48g6ykyqch6tk3nwjlx5xmt2ug79n0ylqtrfwu6\\\\\\",\\\\\\"noble\\\\\\":\\\\\\"cosmos:grand-1:noble19hwcddzyk3r0rr2m7k6rgemzqzeq9kf9unt44vygnydmetzwhtzs6xlt6x\\\\\\"},\\\\\\"accountsPending\\\\\\":[\\\\\\"Avalanche\\\\\\"],\\\\\\"depositAddress\\\\\\":\\\\\\"agoric1lj56zcfftr7w8hgdc749ynt8l8nz4guwf548f097ug9vszsvjeyq8u8upq\\\\\\",\\\\\\"flowCount\\\\\\":1,\\\\\\"flowsRunning\\\\\\":{\\\\\\"flow1\\\\\\":{\\\\\\"amount\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+1000000\\\\\\"},\\\\\\"type\\\\\\":\\\\\\"deposit\\\\\\"}},\\\\\\"nobleForwardingAddress\\\\\\":\\\\\\"noble1f8l404vwnh2p99yqar435fjp5yrclnlyzkm6gw\\\\\\",\\\\\\"policyVersion\\\\\\":1,\\\\\\"positionKeys\\\\\\":[],\\\\\\"rebalanceCount\\\\\\":1,\\\\\\"targetAllocation\\\\\\":{\\\\\\"Aave_Avalanche\\\\\\":\\\\\\"+100\\\\\\"}}\\",\\"slots\\":[\\"board006172\\"]}"]}',
      eventRecord: {
        blockHeight: 5228729n,
        type: 'kvstore',
        event: { type: 'state_change', attributes: [Array] }
      }
    },
    {
      path: 'published.ymax0.portfolios.portfolio64.flows.flow1',
      value: '{"blockHeight":"5228729","values":["{\\"body\\":\\"#{\\\\\\"amount\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+1000000\\\\\\"},\\\\\\"how\\\\\\":\\\\\\"makeAccounts(Avalanche)\\\\\\",\\\\\\"state\\\\\\":\\\\\\"run\\\\\\",\\\\\\"step\\\\\\":0,\\\\\\"type\\\\\\":\\\\\\"deposit\\\\\\"}\\",\\"slots\\":[\\"board006172\\"]}","{\\"body\\":\\"#{\\\\\\"amount\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+1000000\\\\\\"},\\\\\\"how\\\\\\":\\\\\\"localTransfer\\\\\\",\\\\\\"state\\\\\\":\\\\\\"run\\\\\\",\\\\\\"step\\\\\\":1,\\\\\\"steps\\\\\\":[1],\\\\\\"type\\\\\\":\\\\\\"deposit\\\\\\"}\\",\\"slots\\":[\\"board006172\\"]}"]}',
      eventRecord: {
        blockHeight: 5228729n,
        type: 'kvstore',
        event: { type: 'state_change', attributes: [Array] }
      }
    },
    {
      path: 'published.ymax0.portfolios.portfolio64.flows.flow1.steps',
      value: '{"blockHeight":"5228729","values":["{\\"body\\":\\"#[{\\\\\\"amount\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0.Alleged: USDC brand\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+1000000\\\\\\"},\\\\\\"dest\\\\\\":\\\\\\"@agoric\\\\\\",\\\\\\"how\\\\\\":\\\\\\"localTransfer\\\\\\",\\\\\\"src\\\\\\":\\\\\\"\\u003cDeposit\\u003e\\\\\\"},{\\\\\\"amount\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+1000000\\\\\\"},\\\\\\"dest\\\\\\":\\\\\\"@noble\\\\\\",\\\\\\"how\\\\\\":\\\\\\"IBC to Noble\\\\\\",\\\\\\"src\\\\\\":\\\\\\"@agoric\\\\\\"},{\\\\\\"amount\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+1000000\\\\\\"},\\\\\\"dest\\\\\\":\\\\\\"@Avalanche\\\\\\",\\\\\\"how\\\\\\":\\\\\\"CCTP\\\\\\",\\\\\\"src\\\\\\":\\\\\\"@noble\\\\\\"},{\\\\\\"amount\\\\\\":{\\\\\\"brand\\\\\\":\\\\\\"$0\\\\\\",\\\\\\"value\\\\\\":\\\\\\"+1000000\\\\\\"},\\\\\\"dest\\\\\\":\\\\\\"Aave_Avalanche\\\\\\",\\\\\\"how\\\\\\":\\\\\\"Aave\\\\\\",\\\\\\"phases\\\\\\":{},\\\\\\"src\\\\\\":\\\\\\"@Avalanche\\\\\\"}]\\",\\"slots\\":[\\"board006172\\"]}"]}',
      eventRecord: {
        blockHeight: 5228729n,
        type: 'kvstore',
        event: { type: 'state_change', attributes: [Array] }
      }
    }
  ],
  pendingTxEvents: []
}

Logs for CCTP_TO_EVM

Processing pendingTx event published.ymax0.pendingTxs.tx123
New pending tx {
  txId: 'tx123',
  amount: 1000000n,
  destinationAddress: 'eip155:43113:0xf5f6ab6628c552baf819dd66229c2325cc722c71',
  status: 'pending',
  type: 'CCTP_TO_EVM'
}
...
...
...
[tx123] Watching for ERC-20 transfers to: 0xf5f6ab6628c552baf819dd66229c2325cc722c71 with amount: 1000000
[tx123] Transfer detected: token=0x5425890298aed601595a70AB815c96711a31Bc65 from=0x0000000000000000000000000000000000000000 to=0xf5f6AB6628C552bAf819Dd66229C2325CC722C71 amount=1000000 tx=0x6586717776aa178598d31693d11e0affd2a37046db64a00a686fbf4f95671d74
[tx123] ✓ Amount matches! Expected: 1000000, Received: 1000000
transferResult {
  settled: true,
  txHash: '0x6586717776aa178598d31693d11e0affd2a37046db64a00a686fbf4f95671d74',
  success: true
}
RESULT {
  status: {
    id: 'offer-1768988545656',
    invitationSpec: {
      invitationMakerName: 'SettleTransaction',
      previousOffer: 'redeem-2025-10-21T11:34:08.789Z',
      source: 'continuing'
    },
    numWantsSatisfied: 1,
    offerArgs: { status: 'success', txId: 'tx123' },
    payouts: {},
    proposal: {},
    result: 'Transaction settlement processed'
  },
  updated: 'offerStatus'
}
[tx123] CCTP tx resolved

Vstorage link: https://vstorage.agoric.net/?path=published.ymax0.pendingTxs.tx123&endpoint=https%3A%2F%2Fdevnet.rpc.agoric.net%3A443&height=undefined

MAKE_ACCOUNT Tx logs

[tx125] Watching SmartWalletCreated events emitted by 0x4116A7ca92e41A668d72A4999821F18aB66FB9F3
...
...
[tx125] SmartWalletCreated event detected: wallet:0xf5f6ab6628c552baf819dd66229c2325cc722c71
[tx125] ✓ Address matches! Expected: 0xf5f6ab6628c552baf819dd66229c2325cc722c71, Found: 0xf5f6ab6628c552baf819dd66229c2325cc722c71
transferResult {
  settled: true,
  txHash: '0x0cc89c1ccdb4df3795e9157b57e4606996b5ac25762df7960731fc546c4d33ca',
  success: true
}
...
...
RESULT {
  status: {
    id: 'offer-1768988539157',
    invitationSpec: {
      invitationMakerName: 'SettleTransaction',
      previousOffer: 'redeem-2025-10-21T11:34:08.789Z',
      source: 'continuing'
    },
    numWantsSatisfied: 1,
    offerArgs: { status: 'success', txId: 'tx125' },
    payouts: {},
    proposal: {},
    result: 'Transaction settlement processed'
  },
  updated: 'offerStatus'
}
{
  maxRetries: 6,
  retryIntervalMs: 3500,
  message: 'offer-1768988545656'
}
[tx125] MAKE_ACCOUNT tx resolved

Vstorage link: https://vstorage.agoric.net/?path=published.ymax0.pendingTxs.tx125&endpoint=https%3A%2F%2Fdevnet.rpc.agoric.net%3A443&height=undefined

GMP Tx logs

[tx126] Watching transaction status for txId: tx126 at contract: 0xf5f6ab6628c552baf819dd66229c2325cc722c71
...
...
[tx126] ✅ SUCCESS: txId=tx126 txHash=0x09c1d04ea345ec4473055b6ffe4eb6c9641a7052f837ec6124855f43c61fbe7a block=50872960
transferResult {
  settled: true,
  txHash: '0x09c1d04ea345ec4473055b6ffe4eb6c9641a7052f837ec6124855f43c61fbe7a',
  success: true
}
...
...
RESULT {
  status: {
    id: 'offer-1768988589838',
    invitationSpec: {
      invitationMakerName: 'SettleTransaction',
      previousOffer: 'redeem-2025-10-21T11:34:08.789Z',
      source: 'continuing'
    },
    numWantsSatisfied: 1,
    offerArgs: { status: 'success', txId: 'tx126' },
    payouts: {},
    proposal: {},
    result: 'Transaction settlement processed'
  },
  updated: 'offerStatus'
}
[tx126] GMP tx resolved
...

Vstorage link: https://vstorage.agoric.net/?path=published.ymax0.pendingTxs.tx126&endpoint=https%3A%2F%2Fdevnet.rpc.agoric.net%3A443&height=undefined

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other than tests, this file isnt in use. it would make sense to probably remove it entirely and remove tests related to it as well

@rabi-siddique rabi-siddique force-pushed the rs-find-reverted-transactions branch from e4e2e05 to 4047914 Compare January 23, 2026 07:42
@rabi-siddique rabi-siddique force-pushed the rs-find-reverted-transactions branch from 4047914 to 997315d Compare January 23, 2026 07:43
@rabi-siddique rabi-siddique added automerge:rebase Automatically rebase updates, then merge bypass:integration Prevent integration tests from running on PR labels Jan 23, 2026
@mergify mergify bot merged commit e32e7f1 into master Jan 23, 2026
111 of 120 checks passed
@mergify mergify bot deleted the rs-find-reverted-transactions branch January 23, 2026 08:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automerge:rebase Automatically rebase updates, then merge bypass:integration Prevent integration tests from running on PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants